package demo

import (
	"fmt"
	"gitee.com/enzolwb/my-web-scaffold/api"
	"gitee.com/enzolwb/my-web-scaffold/api/v1"
	_ "gitee.com/enzolwb/my-web-scaffold/docs"
	"gitee.com/enzolwb/my-web-scaffold/middleware"
	"gitee.com/enzolwb/my-web-scaffold/middleware/rbac"
	session_auth "gitee.com/enzolwb/my-web-scaffold/middleware/session"
	"gitee.com/enzolwb/my-web-scaffold/models"
	"gitee.com/enzolwb/my-web-scaffold/pkg/export"
	"gitee.com/enzolwb/my-web-scaffold/pkg/qrcode"
	"gitee.com/enzolwb/my-web-scaffold/pkg/setting"
	"gitee.com/enzolwb/my-web-scaffold/pkg/upload"
	"gitee.com/enzolwb/my-web-scaffold/routers/demo"
	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"io"
	"net/http"
	"os"
	"time"
)

func InitRouter() *gin.Engine {
	r := gin.New()

	// 记录请求的日志信息 看情况是否保留
	// LoggerWithFormatter 中间件会将日志写入 gin.DefaultWriter
	// 默认情况下 gin.DefaultWriter 是 os.Stdout
	f, _ := os.Create("./gin.log")
	gin.DefaultWriter = io.MultiWriter(f)

	// 如果需要将日志同时写入文件和控制台，请使用以下代码
	// gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
	r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
		logStr := fmt.Sprintf("%s - [%s] %d \"%s %s %s  %s \"%s\" %s\"\n",
			param.ClientIP,
			param.TimeStamp.Format(time.RFC1123),
			param.StatusCode,
			param.Method,
			param.Path,
			param.Request.Proto,
			param.Latency,
			param.Request.UserAgent(),
			param.ErrorMessage,
		)

		//将控制台信息也输出到文件中
		//mylogger.Debug(logStr)
		return logStr
	}))
	// gin的记录日志结束

	//加载中间件
	r.Use(
		middleware.RecoveryMiddleware(),
		middleware.CORS(),
	)

	//设置开发/生产环境
	gin.SetMode(setting.ServerSetting.RunMode)

	//redis记录session
	store, _ := sessions.NewRedisStore(10, "tcp",
		setting.RedisSetting.Host, setting.RedisSetting.Password, []byte("secret"))
	r.Use(sessions.Sessions("session", store))

	//静态文件路径
	r.StaticFS("/upload/images", http.Dir(upload.GetImageFullPath()))
	r.StaticFS("/qrcode", http.Dir(qrcode.GetQrCodeFullPath()))
	r.StaticFS("/export", http.Dir(export.GetExcelFullPath()))

	//swag文档
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	//鉴权：JWT方式
	r.POST("/auth", api.GetAuth)
	//鉴权：Session方式
	r.POST("/login", api.Login)

	//上传图片
	r.POST("/upload", api.UploadImage)
	//导出标签
	r.POST("/tags/export", v1.ExportTag)

	//设置路由组 为什么他们就是v1呢 属于业务接口 也许会变化DTO
	apiv1 := r.Group("/api/v1")

	//不需要鉴权的
	apiv1.GET("/articles", v1.GetArticles)

	//以下部分为 需要鉴权的

	//apiv1.Use(jwt.JWT())
	apiv1.Use(
		session_auth.SA(),
		//肯定是先看登陆再看是否有权限
		rbac.Authorize(models.Enforcer),
	)
	{
		demo.TagRouteRegister(apiv1)
		demo.ArticleRouteRegister(apiv1)
		//权限组(只有admin才能配置)
		roleGroup := apiv1.Group("/roles")
		roleGroup.PUT("/", api.UpdatePolicy) //更新
		roleGroup.POST("/", api.AddPolicy)   //新增
		roleGroup.GET("/", api.GetPolicy)    //获取
		roleGroup.DELETE("/", api.DelPolicy) //删除
	}

	//只有超级管理员才能配置权限

	return r
}
